/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tpv;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Clase que implementa la interface impuestos
 * que añade soporte para impuestos en XML.
 * @author patri
 */
public class ImpuestoXML implements Impuestos
{

    /**
     * Atributo que nos indica la url del servicio.
     */
    String url;

    /**
     * Constructor que asigna la url
     * @param url Url del servicio
     */
    public ImpuestoXML(String url)
    {
        this.url = url;
    }

    /**
     * Implementa el método de la interface
     * para calcular los impuestos del servicio
     * que devuelve XML
     * @param venta Sobre la cual se calculan los impuestos
     * @return Cantidad de impuestos de la venta
     */
    @Override
    public double calcularImpuestos(Venta venta)
    {
        ArrayList<LinVenta> lineas = (ArrayList<LinVenta>) venta.getLineas();
        double ret = 0;

        for (LinVenta linea : lineas)
        {
            try
            {
                String xml = llamarServicio(linea.getItem().getCodigo());
                double impuesto = procesarXML(linea, xml);
                ret += impuesto;
            }
            catch (Exception ex)
            {
                System.err.println("Algún error sucedió en la conexión con el servicio");

                return 0;
            }
        }
        return ret;
    }

    /**
     * Llamada al servicio para recuperar el XML
     * @param codigo Código de la referencia del producto de una línea
     * @return XML que retorna el servicio
     * @throws Exception
     */
    private String llamarServicio(String codigo) throws Exception
    {
        URL uri = new URL(url + "?producto=" + URLEncoder.encode(codigo));
        URLConnection urlc = uri.openConnection();

        urlc.setDoOutput(true);
        urlc.setAllowUserInteraction(false);

        BufferedReader br = new BufferedReader(new InputStreamReader(urlc.getInputStream()));

        String line;
        StringBuilder sb = new StringBuilder();

        while ((line = br.readLine()) != null)
        {
            sb.append(line);
            sb.append("\n");
        }

        br.close();
        return sb.toString();
    }

    /**
     * Función que procesa el XML para devolver el impuesto
     * sobre una linea de venta
     * @param linea Linea de la venta sobre la que calculamos el impuesto
     * @param xml XML a procesar donde se encuentra la linea
     * @return Impuesto sobre una linea de venta del xml
     */
    private double procesarXML(LinVenta linea, String xml)
    {
        double impuesto = 0;
        try
        {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));

            Document doc = db.parse(is);
            NodeList nodes = doc.getElementsByTagName("impuestos");
            Element element = (Element) nodes.item(0);

            NodeList iva = element.getElementsByTagName("iva");
            Element eiva = (Element) iva.item(0);

            Node niva = eiva.getFirstChild();
            CharacterData civa = (CharacterData) niva;

            //impuesto += (linea.getCantidad() * linea.getItem().getPrecio() - linea.getDescuento()) * (Float.parseFloat(civa.getData()) / 100.0);
			impuesto += Float.parseFloat(civa.getData()) / 100.0;

            nodes = element.getElementsByTagName("especial");

            if (nodes.getLength() > 0)
            {
                Element eesp = (Element) nodes.item(0);
                Node nesp = eesp.getFirstChild();
                CharacterData cesp = (CharacterData) nesp;

                //impuesto += (linea.getCantidad() * linea.getItem().getPrecio() - linea.getDescuento()) * (Float.parseFloat(cesp.getData()) / 100.0);
				impuesto += Float.parseFloat(cesp.getData()) / 100.0;
            }
			
			double precioSin = (linea.getCantidad() * linea.getItem().getPrecio()) / (1 + impuesto);
			
			return ((precioSin - linea.getDescuento()) * impuesto);

            //return impuesto;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return 0;
    }

    public static void main(String[] args)
    {
        Venta v = new Venta(true, false, new Fecha("X", 12, 12));
        v.anyadirLinVenta(new LinVenta(new Producto("061216", "Mi producto", 12.4), 3));

        Impuestos i = new ImpuestoXML("http://artemisa.dlsi.ua.es/~ccachero/isi/impuestos");
        System.out.println(i.calcularImpuestos(v));
    }
}
